#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <memory>
#include <algorithm>
#include "SpaceAsset.h"
#include "CargoShip.h"
#include "GroundStation.h"
#include <cstdlib>

/*-------------------------------------------------
 * 单行文本 → 对象的“简单工厂”
 * @param line  assets.txt 中读取的一行字符串
 * @return      指向派生类对象的基类智能指针
 *------------------------------------------------*/
std::unique_ptr<SpaceAsset> createFromLine(const std::string &line)
{
    // 对一行内容进行我们的字符分割拿到我们的字段值
    //======Begin======
    std::stringstream ss(line);
    std::string kind, id, tmp;
    std::getline(ss, kind, '|'); // 拿到每一行的类型是我们的飞船还是地面基站
    std::getline(ss, id, '|');

    if (kind == "CargoShip")
    {
        double maxLoad;
        std::string status, cargo;
        std::getline(ss, tmp, '|');
        maxLoad = std::stod(tmp);
        std::getline(ss, status, '|');
        std::getline(ss, cargo);
        //调用飞船构造
        return std::make_unique<CargoShip>(id, maxLoad, cargo, status);
    }
    if (kind == "GroundStation")
    {
        std::string loc;
        double cap;
        std::getline(ss, loc, '|');
        std::getline(ss, tmp);
        cap = std::stod(tmp);
        //调用基站构造
        return std::make_unique<GroundStation>(id, loc, cap);
    }
    return nullptr;

    //=======End=======
}

/*-------------------------------------------------
 * 手动加载资产文件
 * @param file  要读取的文本文件名（assets.txt）
 * @param vec   承载所有对象的基类指针容器
 *------------------------------------------------*/
void loadAssets(const std::string &file, std::vector<std::unique_ptr<SpaceAsset>> &vec)
{
    //======Begin======
    vec.clear(); // 确保每次从文件加载数据到内存 不重复
    std::ifstream in(file);
    if (!in.is_open())
    {
        std::cout << "文件 " << file << " 不存在或无法打开。\n";
        return;
    }
    std::string line;
    // 每次从文件中读取一行内容
    int count = 0; // 记录文件中有几条记录
    while (std::getline(in, line))
    {
        auto p = createFromLine(line);
        if (p)
        {
            count++;
            // 加入内存中的资产管理器中
            // 这里我们一定要加move因为
            // 我们对对象的管理的智能指针
            // 是禁止调用对象拷贝函数的
            // 如果我们进行push_back会进行对象
            // 的拷贝从而报错
            // 因此我们用move把对象的管理权转移给
            // vec的智能指针move之后p智能指针为空
            // 就会自动条用析构函数
            vec.push_back(std::move(p));
        }
    }
    std::cout << "---- 已加载" << count << "条资产 ----\n";
    // 下面进行打印
    for (const auto &p : vec)
        p->report();

    //=======End=======
}

/*-------------------------------------------------
 * 保存当前资产到文件
 * @param file  目标文件名（assets.txt）
 * @param vec   要保存的对象容器
 *------------------------------------------------*/
void saveAssets(const std::string &file, const std::vector<std::unique_ptr<SpaceAsset>> &vec)
{
}

/*-------------------------------------------------
 * 一次性打印主菜单
 * @param file  资产文件名，用于提示
 *------------------------------------------------*/
void printmenu(std::string file)
{
    std::cout << "\n===== 火星货运调度控制台 =====\n"
              << "1 加载资产文件 (" << file << ")\n"
              << "2 新建货运任务\n"
              << "3 新建地面站\n"
              << "4 发射飞船\n"
              << "5 飞船返航\n"
              << "6 生成完整日志\n"
              << "7 取消货运任务（删除）\n"
              << "8 保存到资产文件\n"
              << "0 退出\n请选择：";
}
int main()
{
    // 资产文件名
    const std::string file = "assets.txt";
    // 内存中的资产列表 用智能指针进行管理
    std::vector<std::unique_ptr<SpaceAsset>> assets;

    int choice;
    do
    {
        printmenu(file);
        std::cin >> choice;
        switch (choice)
        {
        case 1:
        {
            loadAssets(file, assets);
            break;
        }
        case 2:
        {
            break;
        }
        case 3:
        {
            break;
        }
        case 4:
        {
            break;
        }
        case 5:
        {
            break;
        }
        case 6:
        {
            break;
        }
        case 7:
        {
            break;
        }
        case 8:
        {
            break;
        }
        case 0:
        {
            break;
        }
        default:
        {
            break;
        }
        }

    } while (choice);
    return 0;
}
